using System;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath ;
using EnvDTE;
using AopDotNet.CodeModelXMLTreeBuilder;
using AopDotNet.Editor ;
using System.Collections ;
using System.Text.RegularExpressions  ;
using System.Text;
using System.IO ;
using System.CodeDom.Compiler ;
using System.CodeDom;


namespace AopDotNet
{
	namespace AspectWeaver
	{
		/// <summary>
		/// 
		/// </summary>
		public class Introducer
		{
			private ICodeGenerator codeGenerator;
			private CodeModelBuilder codeTree;
			public Introducer(ICodeGenerator codeGenerator,CodeModelBuilder codeTree)
			{
				this.codeGenerator = codeGenerator;
				this.codeTree =codeTree;
			}
			public void AddToClass(CodeClass theClass,XmlNode addedNode,EditingMonitor monitor)
			{
				if (addedNode.Name =="interface")
				{
					AddInterfaceToClass(theClass,addedNode,monitor);
					
				}
				else
				{
					CodeElement addedElement=Helper.GetAspectElement (addedNode.Attributes ["name"].Value ,addedNode.Name ,addedNode.Attributes ["aspect"].Value,codeTree );
					if (addedElement==null)/*Error Handling*/
						return;
					switch(addedNode .Name )
					{
						case "method":
							CodeEditor.AddMethodToClass(theClass,(CodeFunction)addedElement,false,"",codeGenerator ,monitor);
							break;
						case "member":
							CodeEditor.AddVariableToClass(theClass,(CodeVariable )addedElement,monitor);
							break;
						case "attribute":
							CodeEditor.AddAttributeToClass(theClass,(CodeAttribute)addedElement,monitor);
							break;
						case "constructor":
							CodeEditor.AddConstructorToClass(theClass,(CodeFunction )addedElement,monitor);
							break;
					
					}
				}

			}
			private void AddInterfaceToClass(CodeClass theClass,XmlNode addedNode,EditingMonitor monitor)
			{
				string interfaceName=addedNode.Attributes ["name"].Value;
				CodeElement addedElement=codeTree.SearchForElement("//interfaces/interface[@name='"+interfaceName+"']");
				if (addedElement==null)/*Error Handling*/
					return;
				CodeInterface theInterface=(CodeInterface )addedElement;
				//add the interface to the bases list
				CodeEditor.AddToBases(theClass ,theInterface.Name ,true,codeGenerator,monitor );
				//CodeEditor.AddInterfaceToClass(addedNode,codeTree ,codeGenerator,monitor );
					
				//add the interface methods to the class
				XmlNodeList methodsNodes=codeTree .SearchForElements ("//interface[@name='"+theInterface.Name +"']/methods/method");
				string aspectName=addedNode.Attributes ["aspect"].Value ;
				foreach (XmlNode methodNode in methodsNodes )
				{
					string methodName=methodNode.Attributes ["name"].Value ;
					string methodAccess=methodNode.Attributes ["access"].Value ;
					string methodReturn=methodNode.Attributes ["return"].Value ;
					CodeFunction interfaceMethod=(CodeFunction)codeTree.SearchForElement("//aspect[@name='"+aspectName+"']/descendant::method[@name='"+methodName+"'][@access='"+methodAccess +"'][@return='"+methodReturn+"']");
					if (interfaceMethod ==null)/*Error Handling*/ //the aspect desn't contain the implemented interface function
						continue;
					else
					{
						CodeEditor.AddMethodToClass(theClass,interfaceMethod,true,theInterface.Name ,codeGenerator ,monitor );
					}
				}
			}
			public void AddToNameSpace(EnvDTE.CodeNamespace theNamespace,XmlNode addedNode,EditingMonitor monitor)
			{
				CodeElement addedElement=Helper.GetAspectElement (addedNode.Attributes ["name"].Value ,addedNode.Name ,addedNode.Attributes ["aspect"].Value ,codeTree);
				if (addedElement==null)/*Error Handling*/
					return;
				switch(addedNode .Name )
				{
					case "class":
						CodeEditor.AddClassToNamespace(theNamespace,(CodeClass )addedNode,monitor);
						break;
					case "interface":
						CodeEditor.AddInterfaceToNamespace(theNamespace,(CodeInterface )addedNode,monitor);
						break;
				}
			}
		
			public void AddToMethod(CodeFunction theFunction,XmlNode addedNode)
			{
				CodeElement addedElement=Helper.GetAspectElement (addedNode.Attributes ["name"].Value ,addedNode.Name ,addedNode.Attributes ["aspect"].Value ,codeTree);
				switch(addedNode .Name )
				{
					case "attribute":
						CodeEditor.AddAttributeToMethod(theFunction,(CodeAttribute)addedElement);
						break;
				}
			}
			public void AddToVariable(CodeVariable theVar,XmlNode addedNode)
			{
			}
		
		}
	}
}